package com.swcw.platform.utils;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup;

/**
 * Excel工具类
 * 
 * @see:
 * @Company:江苏鸿信系统集成有限公司微信开发组
 * @author 杨坚
 * @Time 2016年9月28日
 * @version 1.0v
 */
public class ExcelStUtil {

	class Row {
		private List<String> result;

		public List<String> getResult() {
			return result;
		}

		public void setResult(List<String> result) {
			this.result = result;
		}
	}

	class Worksheet {
		private String sheet;

		private int columnNum;

		private int rowNum;

		private List<String> title;

		private List<Row> rows;

		public String getSheet() {
			return sheet;
		}

		public void setSheet(String sheet) {
			this.sheet = sheet;
		}

		public List<Row> getRows() {
			return rows;
		}

		public void setRows(List<Row> rows) {
			this.rows = rows;
		}

		public int getColumnNum() {
			return columnNum;
		}

		public void setColumnNum(int columnNum) {
			this.columnNum = columnNum;
		}

		public int getRowNum() {
			return rowNum;
		}

		public void setRowNum(int rowNum) {
			this.rowNum = rowNum;
		}

		public List<String> getTitle() {
			return title;
		}

		public void setTitle(List<String> title) {
			this.title = title;
		}
	}

	@SuppressWarnings("rawtypes")
	public void export(OutputStream outputStream, List target)
			throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
		long startTime = System.currentTimeMillis();

		StringTemplateGroup stGroup = new StringTemplateGroup("stringTemplate");
		// 解决可能发生的中文乱码
		stGroup.setFileCharEncoding("UTF-8");
		// 写入excel文件头部信息
		StringTemplate head = stGroup.getInstanceOf("com/swcw/platform/utils/excel/head");
		PrintWriter writer = new PrintWriter(new BufferedOutputStream(outputStream));
		writer.print(head.toString());
		writer.flush();

		int totalRowNum = target.size();
		int maxRowNum = 60000;
		int sheets = totalRowNum % 60000 == 0 ? (totalRowNum / maxRowNum) : (totalRowNum / maxRowNum + 1);
		// excel单表最大行数是65535

		List record = target;
		List<String> title = new ArrayList<String>();
		List<Method> getMethods = new ArrayList<Method>();
		Class<?> clazz = record.get(0).getClass();

		Field[] fields = clazz.getDeclaredFields();
		if (fields != null && fields.length > 0) {
			for (Field field : fields) {
				if (!"serialVersionUID".equals(field.getName())) {
					title.add(field.getName());
					getMethods.add(clazz.getDeclaredMethod(
							"get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1)));
				}
			}
		}
		int columnLength = title.size();

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

		// 写入excel文件数据信息
		for (int i = 0; i < sheets; i++) {
			StringTemplate body = stGroup.getInstanceOf("com/swcw/platform/utils/excel/body");
			Worksheet worksheet = new Worksheet();
			worksheet.setTitle(title);
			worksheet.setSheet(" " + (i + 1) + " ");
			worksheet.setColumnNum(columnLength);
			worksheet.setRowNum(maxRowNum + 1);
			List<Row> rows = new ArrayList<Row>();
			int startIndex = i * maxRowNum;
			int endIndex = Math.min((i + 1) * maxRowNum - 1, totalRowNum - 1);
			for (int j = startIndex; j <= endIndex; j++) {
				Row row = new Row();
				List<String> result = new ArrayList<String>(columnLength);
				for (int n = 0; n < columnLength; n++) {
					Object value = getMethods.get(n).invoke(record.get(j));
					if (value == null) {
						result.add("");
					} else {
						if (value instanceof Date) {
							result.add(sdf.format((Date) value));
						} else {
							result.add(value.toString());
						}
					}

				}
				row.setResult(result);
				rows.add(row);
			}
			worksheet.setRows(rows);
			body.setAttribute("worksheet", worksheet);
			writer.print(body.toString());
			writer.flush();
			rows.clear();
			rows = null;
			worksheet = null;
			body = null;
			Runtime.getRuntime().gc();
			System.out.println("正在生成excel文件的 sheet" + (i + 1));
		}

		// 写入excel文件尾部
		writer.print("</Workbook>");
		writer.flush();
		writer.close();
		System.out.println("生成excel文件完成");
		long endTime = System.currentTimeMillis();
		System.out.println("用时=" + ((endTime - startTime) / 1000) + "秒");
	}

	public static void main(String[] args)
			throws IOException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
//		List<Sample> result = new ArrayList<Sample>();
//		for (int i = 0; i < 60000; i++) {
//			result.add(new Sample("放大双方的" + String.valueOf(i), String.valueOf(i)));
//		}
//		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//		ExcelStUtil excel = new ExcelStUtil();
//		excel.export(byteArrayOutputStream, result);
//		File file = new File("E:/output2.xls");
//		OutputStream output = new FileOutputStream(file);
//		BufferedOutputStream bufferedOutput = new BufferedOutputStream(output);
//		bufferedOutput.write(byteArrayOutputStream.toByteArray());
//		bufferedOutput.write(byteArrayOutputStream.toString().getBytes("UTF-8"));
//		bufferedOutput.flush();
//		bufferedOutput.close();

	}
}
